package com.xdl.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xdl.common.constants.CommonConstants;
import com.xdl.common.utils.StringUtils;
import com.xdl.modules.system.entity.SysPermission;
import com.xdl.modules.system.mapper.SysPermissionMapper;
import com.xdl.modules.system.service.SysDepartPermissionService;
import com.xdl.modules.system.service.SysDepartRolePermissionService;
import com.xdl.modules.system.service.SysPermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xdl.modules.system.service.SysRolePermissionService;
import com.mzlion.core.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author iron guo
 * @since 2022-03-08
 */
@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements SysPermissionService {

    @Autowired
    private SysDepartRolePermissionService departRolePermissionService;

    @Autowired
    private SysDepartPermissionService departPermissionService;

    @Autowired
    private SysRolePermissionService rolePermissionService;

    @Override
    public List<SysPermission> queryByUser(String username) {
        return this.baseMapper.queryByUser(username);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editPermission(SysPermission permission) {
        SysPermission p = this.baseMapper.selectById(permission.getId());
        //TODO 该节点判断是否还有子节点
        Assert.notNull(p, "未找到菜单信息!");
        permission.setUpdateTime(LocalDateTime.now());
        //Step1.判断是否是一级菜单，是的话清空父菜单ID首页
        if (CommonConstants.MENU_TYPE_0.equals(permission.getMenuType())) {
            permission.setParentId("");
        }
        //Step2.判断菜单下级是否有菜单，无则设置为叶子节点
        int count = this.count(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, permission.getId()));
        if (count == 0) {
            permission.setLeaf(true);
        }
        this.updateById(permission);
        //如果当前菜单的父菜单变了，则需要修改新父菜单和老父菜单的，叶子节点状态
        String pid = permission.getParentId();
        if ((StringUtils.isNotEmpty(pid) && !pid.equals(p.getParentId())) || StringUtils.isEmpty(pid) && StringUtils.isNotEmpty(p.getParentId())) {
            //a.设置新的父菜单不为叶子节点
            this.baseMapper.setMenuLeaf(pid, 0);
            //b.判断老的菜单下是否还有其他子菜单，没有的话则设置为叶子节点
            int cc = this.count(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, p.getParentId()));
            if (cc == 0) {
                if (StringUtils.isNotEmpty(p.getParentId())) {
                    this.baseMapper.setMenuLeaf(p.getParentId(), 1);
                }
            }
        }
        return true;
    }

    @Override
    public Boolean deletePermission(String id) {
        SysPermission sysPermission = this.getById(id);
        Assert.notNull(sysPermission, "未找到菜单信息!");
        String pid = sysPermission.getParentId();
        if(StringUtils.isNotEmpty(pid)) {
            int count = this.count(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, pid));
            if(count==1) {
                //若父节点无其他子节点，则该父节点是叶子节点
                this.baseMapper.setMenuLeaf(pid, 1);
            }
        }
        this.baseMapper.deleteById(id);
        // 该节点可能是子节点但也可能是其它节点的父节点,所以需要级联删除
        this.removeChildrenBy(sysPermission.getId());
        //关联删除
        Map map = new HashMap<>();
        map.put("permission_id",id);
        //删除角色授权表
        rolePermissionService.removeByMap(map);
        //删除部门权限表
        departPermissionService.removeByMap(map);
        //删除部门角色授权
        departRolePermissionService.removeByMap(map);
        return true;
    }

    @Override
    public boolean addPermission(SysPermission permission) {
        //----------------------------------------------------------------------
        //判断是否是一级菜单，是的话清空父菜单
        if(CommonConstants.MENU_TYPE_0.equals(permission.getMenuType())) {
            permission.setParentId(null);
        }
        //----------------------------------------------------------------------
        String pid = permission.getParentId();
        if(StringUtils.isNotEmpty(pid)) {
            //设置父节点不为叶子节点
            this.baseMapper.setMenuLeaf(pid, 0);
        }
        permission.setCreateTime(LocalDateTime.now());
        permission.setDelFlag(0);
        permission.setLeaf(true);
        this.save(permission);
        return true;
    }


    /**
     * 根据父id删除其关联的子节点数据
     *
     * @return
     */
    public void removeChildrenBy(String parentId) {
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        // 封装查询条件parentId为主键,
        query.eq(SysPermission::getParentId, parentId);
        // 查出该主键下的所有子级
        List<SysPermission> permissionList = this.list(query);
        if (permissionList != null && permissionList.size() > 0) {
            String id = ""; // id
            int num = 0; // 查出的子级数量
            // 如果查出的集合不为空, 则先删除所有
            this.remove(query);
            // 再遍历刚才查出的集合, 根据每个对象,查找其是否仍有子级
            for (int i = 0, len = permissionList.size(); i < len; i++) {
                id = permissionList.get(i).getId();
                Map map = new HashMap<>();
                map.put("permission_id",id);
                //删除角色授权表
                rolePermissionService.removeByMap(map);
                //删除部门权限表
                departPermissionService.removeByMap(map);
                //删除部门角色授权
                departRolePermissionService.removeByMap(map);
                num = this.count(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getParentId, id));
                // 如果有, 则递归
                if (num > 0) {
                    this.removeChildrenBy(id);
                }
            }
        }
    }
}
